using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel;
using OpenComposite.Workflow;
using OpenComposite.EII.Repository;
using System.Xml;
using System.IO;
using System.Workflow.ComponentModel.Serialization;

namespace OpenComposite.EII.Designer.Workflow.Forms
{
	public partial class FormWFInterface : WeifenLuo.WinFormsUI.Docking.DockContent
	{
		#region Initialization
		public FormWFInterface(IServiceProvider serviceProvider)
		{
			if ( serviceProvider == null )
				throw new ArgumentNullException("serviceProvider");

			_serviceProvider = serviceProvider;
			_workflow = null;

			InitializeComponent();

			init();
		}
		private void init()
		{
			DataTable dt = Global.Data.GetDataTypes();
			foreach ( DataRow row in dt.Rows ) {
				colVariableDataType.Items.Add(row["datatype"].ToString());
			}
		}
		#endregion

		#region Public Members

		#region Properties
		public bool MethodsTabVisible
		{
			get { return tabCtrlWFInterface.TabPages.Contains(tabMethods); }
			set
			{
				if ( value ) {	// show
					if ( !this.MethodsTabVisible ) tabCtrlWFInterface.TabPages.Add(tabMethods);
				} else {		// hide
					if ( this.MethodsTabVisible ) tabCtrlWFInterface.TabPages.Remove(tabMethods);
				}
				tsbtnAddMethod.Visible = value;
				miEventNewMethod.Visible = value;
				tsSepEventNew.Visible = value || miEventNewVariable.Visible;
				miVariableNewMethod.Visible = value;
				tsSepVariableNew.Visible = value || miVariableNewEvent.Visible;
			}
		}
		public bool EventsTabVisible
		{
			get { return tabCtrlWFInterface.TabPages.Contains(tabEvents); }
			set
			{
				if ( value ) {	// show
					if ( !this.EventsTabVisible ) tabCtrlWFInterface.TabPages.Add(tabEvents);
				} else {		// hide
					if ( this.EventsTabVisible ) tabCtrlWFInterface.TabPages.Remove(tabEvents);
				}
				tsbtnAddEvent.Visible = value;
				miMethodNewEvent.Visible = value;
				tsSepMethodNew.Visible = value || miMethodNewVariable.Visible;
				miVariableNewEvent.Visible = value;
				tsSepVariableNew.Visible = value || miVariableNewMethod.Visible;
			}
		}
		public bool VariablesTabVisible
		{
			get { return tabCtrlWFInterface.TabPages.Contains(tabVariables); }
			set
			{
				if ( value ) {	// show
					if ( !this.VariablesTabVisible ) tabCtrlWFInterface.TabPages.Add(tabVariables);
				} else {		// hide
					if ( this.VariablesTabVisible ) tabCtrlWFInterface.TabPages.Remove(tabVariables);
				}
				tsbtnAddVariable.Visible = value;
				miMethodNewVariable.Visible = value;
				tsSepMethodNew.Visible = value || miMethodNewEvent.Visible;
				miEventNewVariable.Visible = value;
				tsSepEventNew.Visible = value || miMethodNewEvent.Visible;
			}
		}
		#endregion

		#region Methods
		public void Init(Repository.Workflow workflow)
		{
			if ( workflow == null )
				throw new ArgumentNullException("workflow");

			_workflow = workflow;

			// init Methods List
			_bsMethods = new BindingSource();
			_bsMethods.AllowNew = true;
			_bsMethods.AddingNew += new AddingNewEventHandler(_bsMethods_AddingNew);
			_bsMethods.DataSource = _workflow.Interface.Methods;

			dgvMethods.AutoGenerateColumns = false;
			dgvMethods.DataSource = _bsMethods;
			dgvMethods.ClearSelection();

			// init Events List
			_bsEvents = new BindingSource();
			_bsEvents.AllowNew = true;
			_bsEvents.AddingNew += new AddingNewEventHandler(_bsEvents_AddingNew);
			_bsEvents.DataSource = _workflow.Interface.Events;

			dgvEvents.AutoGenerateColumns = false;
			dgvEvents.DataSource = _bsEvents;
			dgvEvents.ClearSelection();

			// init Variables List
			_bsVariables = new BindingSource();
			_bsVariables.AllowNew = true;
			_bsVariables.AddingNew += new AddingNewEventHandler(_bsFields_AddingNew);
			_bsVariables.CurrentChanged += new EventHandler(_bsVariables_CurrentChanged);
			_bsVariables.CurrentItemChanged += new EventHandler(_bsVariables_CurrentItemChanged);
			_bsVariables.ListChanged += new ListChangedEventHandler(_bsVariables_ListChanged);
			_bsVariables.DataSource = _workflow.Interface.Fields;

			dgvVariables.AutoGenerateColumns = false;
			dgvVariables.DataSource = _bsVariables;
			dgvVariables.ClearSelection();
		}

		#endregion

		#endregion

		#region Private Members

		#region Fields

		private IServiceProvider _serviceProvider;
		private Repository.Workflow _workflow;

		private BindingSource _bsMethods;
		private BindingSource _bsEvents;
		private BindingSource _bsVariables;

		private Repository.WorkflowField _currentField = null;
		private string _currentOldName = null;
		private string _currentOldType = null;

		#endregion

		#region Methods

		private void addMethod()
		{
			tabCtrlWFInterface.SelectTab(tabMethods);
			_bsMethods.AddNew();
			dgvMethods.CurrentCell = dgvMethods.CurrentRow.Cells["colMethodName"];
			dgvMethods.BeginEdit(true);
		}
		private void addEvent()
		{
			tabCtrlWFInterface.SelectTab(tabEvents);
			_bsEvents.AddNew();
			dgvEvents.CurrentCell = dgvEvents.CurrentRow.Cells["colEventName"];
			dgvEvents.BeginEdit(true);
		}
		private void addVariable()
		{
			tabCtrlWFInterface.SelectTab(tabVariables);
			_bsVariables.AddNew();
			dgvVariables.CurrentCell = dgvVariables.CurrentRow.Cells[colVariableName.Index];
			dgvVariables.BeginEdit(true);
		}

		private void removeMethod()
		{
			try {
				//DialogResult result = MessageBox.Show("Deleting a method will delete all activities in the " +
				//                            "process that use this method. Therefor the process needs to be saved." + Environment.NewLine +
				//                            "Do you want to continue?" + Environment.NewLine +
				//                            "Yes: Save the process. All activities using this method will be deleted." + Environment.NewLine +
				//                            "No: Don't save the process. You have do delete all activities using this method manually!",
				//    "Delete Method", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
				DialogResult result = MessageBox.Show("Deleting a Method from the Interface will delete the assigned elements from the process. Additionally, the process will be saved. This action cannot be undone. Do you wish to continue?",
					"Delete Method", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
				if ( result == DialogResult.OK ) {
					if ( dgvMethods.SelectedRows.Count < 1 ) return;
					Repository.WorkflowMethod meth = dgvMethods.SelectedRows[0].DataBoundItem as Repository.WorkflowMethod;
					if ( meth == null ) return;
					WorkflowController wfController = _serviceProvider as WorkflowController;
					if ( wfController == null ) return;
					wfController.Save(true);
					CompositeActivity root = Helpers.GetRootActivity(_workflow) as CompositeActivity;

					removeMethodsRecursive(root, meth, wfController);

					WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
					StringBuilder sb = new StringBuilder();
					XmlWriterSettings settings = new XmlWriterSettings();
					settings.ConformanceLevel = ConformanceLevel.Fragment;
					settings.OmitXmlDeclaration = true;
					try {
						using ( XmlWriter xw = XmlWriter.Create(sb, settings) ) {
							serializer.Serialize(xw, root);
							xw.Flush();
						}
					} catch { }
					_workflow.XOML = sb.ToString();
					_workflow.Save();
					wfController.LoadWorkflow(_workflow);
					dgvMethods.Rows.RemoveAt(dgvMethods.SelectedRows[0].Index);
				}
			} catch { }
		}

		private void removeEvent()
		{
			try {
				//DialogResult result = MessageBox.Show("Deleting an event will delete all activities in the " +
				//                            "process that use this event. Therefor the process needs to be saved." + Environment.NewLine +
				//                            "Do you want to continue?" + Environment.NewLine +
				//                            "Yes: Save the process. All activities using this event will be deleted." + Environment.NewLine +
				//                            "No: Don't save the process. You have do delete all activities using this event manually!",
				//                        "Delete Event", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
				DialogResult result = MessageBox.Show("Deleting an Event from the Interface will delete the assigned elements from the process. Additionally, the process will be saved. This action cannot be undone. Do you wish to continue?",
					"Delete Method", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
				if ( result == DialogResult.OK ) {
					if ( dgvEvents.SelectedRows.Count < 1 ) return;
					Repository.WorkflowEvent evt = dgvEvents.SelectedRows[0].DataBoundItem as Repository.WorkflowEvent;
					if ( evt == null ) return;
					WorkflowController wfController = _serviceProvider as WorkflowController;
					if ( wfController == null ) return;
					wfController.Save(true);
					CompositeActivity root = Helpers.GetRootActivity(_workflow) as CompositeActivity;

					Debug.WriteLine(root.Activities.Count);

					removeEventRecursive(root, evt, wfController);

					WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
					StringBuilder sb = new StringBuilder();
					XmlWriterSettings settings = new XmlWriterSettings();
					settings.ConformanceLevel = ConformanceLevel.Fragment;
					settings.OmitXmlDeclaration = true;
					try {
						using ( XmlWriter xw = XmlWriter.Create(sb, settings) ) {
							serializer.Serialize(xw, root);
							xw.Flush();
						}
					} catch { }
					_workflow.XOML = sb.ToString();
					_workflow.Save();
					wfController.LoadWorkflow(_workflow);
					dgvEvents.Rows.RemoveAt(dgvEvents.SelectedRows[0].Index);
				}
			} catch { }
		}

		private void removeMethodsRecursive(CompositeActivity cact, WorkflowMethod meth, WorkflowController wfController)
		{
			for ( int i = cact.Activities.Count - 1; i >= 0; i-- ) {
				ILogicalActivity act = cact.Activities[i] as ILogicalActivity;
				if ( act == null ) {
					if ( cact.Activities[i] is CompositeActivity ) {
						removeMethodsRecursive(cact.Activities[i] as CompositeActivity, meth, wfController);
					} else {
						continue;
					}
				}
				if ( act is LogicalMethodCallActivity ) {
					LogicalActivity logact = Global.Data.RepositoryService.GetItem<LogicalActivity>(act.LogicalActivityId);
					if ( logact == null ) continue;
					if ( logact.WorkflowMethodID == meth.ID ) {
						wfController.WorkflowLoader.RemoveActivityFromDesigner((Activity)act);
						cact.Activities.Remove((Activity)act);
					}
				}
			}

		}

		private void removeEventRecursive(CompositeActivity cact, WorkflowEvent evt, WorkflowController wfController)
		{
			for ( int i = cact.Activities.Count - 1; i >= 0; i-- ) {
				ILogicalActivity act = cact.Activities[i] as ILogicalActivity;
				if ( act == null ) {
					if ( cact.Activities[i] is CompositeActivity ) {
						removeEventRecursive(cact.Activities[i] as CompositeActivity, evt, wfController);
					} else {
						continue;
					}
				}
				if ( act is LogicalInputActivity ) {
					LogicalActivity logact = Global.Data.RepositoryService.GetItem<LogicalActivity>(act.LogicalActivityId);
					if ( logact == null ) continue;
					if ( logact.WorkflowEventID == evt.ID ) {
						wfController.WorkflowLoader.RemoveActivityFromDesigner((Activity)act);
						cact.Activities.Remove((Activity)act);
					}
				}
			}
		}

		#endregion

		#region Event Handler

		private void tsbtnAddMethod_Click(object sender, EventArgs e)
		{
			addMethod();
		}
		private void tsbtnAddEvent_Click(object sender, EventArgs e)
		{
			addEvent();
		}
		private void tsbtnAddVariable_Click(object sender, EventArgs e)
		{
			addVariable();
		}

		private void _bsMethods_AddingNew(object sender, AddingNewEventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)_serviceProvider.GetService(typeof(RepositoryService));
			Debug.Assert(repSvc != null);

			Repository.IRepositoryItem parentItem = null;
			Repository.WorkflowMethod wm = repSvc.GetNewItem<Repository.WorkflowMethod>(false, ref parentItem);
			wm.Workflow = _workflow;
			e.NewObject = wm;
		}
		private void _bsFields_AddingNew(object sender, AddingNewEventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)_serviceProvider.GetService(typeof(RepositoryService));
			Debug.Assert(repSvc != null);

			Repository.IRepositoryItem parentItem = null;
			Repository.WorkflowField field =
				repSvc.GetNewItem<Repository.WorkflowField>(false, ref parentItem);
			field.Name = "variable1";
			field.DataType = "string";
			field.CreateContainerBusinessObject();
			Global.Data.AddRepositoryHierarchy(_workflow.ProcessVariablesFolder, field, Global.Status.CurrentRepositoryId);
			e.NewObject = field;

			TypeProvider typeProvider = (TypeProvider)_serviceProvider.GetService(typeof(ITypeProvider));
			MemberCreationService memberCreate = (MemberCreationService)_serviceProvider.GetService(typeof(IMemberCreationService));
			WorkflowLoader loader = (WorkflowLoader)_serviceProvider.GetService(typeof(WorkflowDesignerLoader));
			Debug.Assert(typeProvider != null);
			Debug.Assert(memberCreate != null);

			memberCreate.CreateProperty(_workflow.ExtendedProperties.FullName, field.Name, typeof(string),
										null, true, false, false, null, false);

			loader.RefreshAllCode();
		}
		private void _bsEvents_AddingNew(object sender, AddingNewEventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)_serviceProvider.GetService(typeof(RepositoryService));
			Debug.Assert(repSvc != null);

			Repository.IRepositoryItem parentItem = null;
			Repository.WorkflowEvent we = repSvc.GetNewItem<Repository.WorkflowEvent>(false, ref parentItem);
			we.Workflow = _workflow;
			e.NewObject = we;
		}

		#region Drag & Drop
		private void dgvMethods_DragDrop(object sender, DragEventArgs e)
		{
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Repository.BusinessObject bo = (Repository.BusinessObject)e.Data.GetData(typeof(Repository.BusinessObject));
			Point ptClient = dgvMethods.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvMethods.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colMethodInputBO.Index ) {
					( (Repository.WorkflowMethod)dgvMethods.Rows[hti.RowIndex].DataBoundItem )
						.InputBusinessObject = bo;
				} else if ( hti.ColumnIndex == colMethodOutputBO.Index ) {
					( (Repository.WorkflowMethod)dgvMethods.Rows[hti.RowIndex].DataBoundItem )
						.OutputBusinessObject = bo;
				}
				dgvMethods.UpdateCellValue(hti.ColumnIndex, hti.RowIndex);
			}
		}
		private void dgvMethods_DragOver(object sender, DragEventArgs e)
		{
			e.Effect = DragDropEffects.None;
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Point ptClient = dgvMethods.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvMethods.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colMethodInputBO.Index ) {
					e.Effect = DragDropEffects.Link;
				} else if ( hti.ColumnIndex == colMethodOutputBO.Index ) {
					e.Effect = DragDropEffects.Link;
				}
			}
		}
		private void dgvMethods_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
			
		}

		private void dgvEvents_DragDrop(object sender, DragEventArgs e)
		{
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Repository.BusinessObject bo = (Repository.BusinessObject)e.Data.GetData(typeof(Repository.BusinessObject));
			Point ptClient = dgvEvents.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvEvents.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colEventBO.Index ) {
					( (Repository.WorkflowEvent)dgvEvents.Rows[hti.RowIndex].DataBoundItem )
						.BusinessObject = bo;
				}
				dgvEvents.UpdateCellValue(hti.ColumnIndex, hti.RowIndex);
			}
		}
		private void dgvEvents_DragOver(object sender, DragEventArgs e)
		{
			e.Effect = DragDropEffects.None;
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Point ptClient = dgvEvents.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvEvents.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colEventBO.Index ) {
					e.Effect = DragDropEffects.Link;
				}
			}
		}
		private void dgvEvents_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{

		}

		private void dgvVariables_DragDrop(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(Repository.Noun)) ) {
				Repository.Noun noun = e.Data.GetData(typeof(Repository.Noun)) as Repository.Noun;
				Repository.WorkflowField field = _bsVariables.AddNew() as Repository.WorkflowField;
				field.Name = noun.Name;
				field.WorkflowID = _workflow.ID;
				field.DataType = noun.DataType;
				field.Save();
				WorkflowLoader loader = (WorkflowLoader)_serviceProvider.GetService(typeof(WorkflowDesignerLoader));
				if ( loader != null ) {
					loader.Workflow.Save();
					loader.Workflow.Reload();
					loader.RefreshAllCode();
				}

				return;
			}
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Repository.BusinessObject bo = (Repository.BusinessObject)e.Data.GetData(typeof(Repository.BusinessObject));
			Point ptClient = dgvVariables.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvVariables.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colEventBO.Index ) {
					( (Repository.WorkflowField)dgvVariables.Rows[hti.RowIndex].DataBoundItem )
						.BusinessObject = bo;
				}
				dgvVariables.UpdateCellValue(hti.ColumnIndex, hti.RowIndex);
				dgvVariables.AutoResizeColumns();
			}
		}
		private void dgvVariables_DragOver(object sender, DragEventArgs e)
		{
			e.Effect = DragDropEffects.None;
			if ( e.Data.GetDataPresent(typeof(Repository.Noun)) ) {
				e.Effect = DragDropEffects.Copy;
				return;
			}
			if ( !e.Data.GetDataPresent(typeof(Repository.BusinessObject)) ) {
				return;
			}
			Point ptClient = dgvVariables.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvVariables.HitTest(ptClient.X, ptClient.Y);
			if ( hti.RowIndex >= 0 ) {
				if ( hti.ColumnIndex == colVariableDataType.Index ) {
					e.Effect = DragDropEffects.Link;
				}
			}
		}
		private void dgvVariables_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{

		}

		// start drag
		private void dgvMethods_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Left && e.RowIndex >= 0 && !dgvMethods.IsCurrentCellInEditMode ) {
				Repository.WorkflowMethod wm = dgvMethods.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowMethod;
				if ( wm != null ) {
					// start drag&drop
					DataObject dobj = new DataObject();
					try {
						wm.SetDragDropDataObject(dobj);
						dgvMethods.DoDragDrop(dobj, DragDropEffects.All);
					} catch { }
				}
			}
		}
		private void dgvEvents_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Left && e.RowIndex >= 0 && !dgvEvents.IsCurrentCellInEditMode ) {
				Repository.WorkflowEvent we = dgvEvents.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowEvent;
				if ( we != null ) {
					// start drag&drop
					DataObject dobj = new DataObject();
					try {
						we.SetDragDropDataObject(dobj);
						dgvEvents.DoDragDrop(dobj, DragDropEffects.All);
					} catch { }
				}
			}
		}
		private void dgvVariables_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Left ) {
				// start drag&drop

			}
		}

		#endregion

		#region Context Menu
		private void contextMethods_Opening(object sender, CancelEventArgs e)
		{
			Point ptClient = dgvMethods.PointToClient(Cursor.Position);
			DataGridView.HitTestInfo hti = dgvMethods.HitTest(ptClient.X, ptClient.Y);
			if ( hti.Type == DataGridViewHitTestType.ColumnHeader ) {
				e.Cancel = true;
			} else if ( hti.Type == DataGridViewHitTestType.Cell ) {
				miMethodRemove.Enabled = true;
				miMethodRemoveInput.Enabled = true;
				miMethodRemoveOutput.Enabled = true;
				dgvMethods.Rows[hti.RowIndex].Selected = true;
			} else {
				miMethodRemove.Enabled = false;
				miMethodRemoveInput.Enabled = false;
				miMethodRemoveOutput.Enabled = false;
				dgvMethods.ClearSelection();
			}
		}
		private void contextEvents_Opening(object sender, CancelEventArgs e)
		{
			Point ptClient = dgvEvents.PointToClient(Cursor.Position);
			DataGridView.HitTestInfo hti = dgvEvents.HitTest(ptClient.X, ptClient.Y);
			if ( hti.Type == DataGridViewHitTestType.ColumnHeader ) {
				e.Cancel = true;
			} else if ( hti.Type == DataGridViewHitTestType.Cell ) {
				miEventRemove.Enabled = true;
				miEventRemoveBObj.Enabled = true;
				dgvEvents.Rows[hti.RowIndex].Selected = true;
			} else {
				miEventRemove.Enabled = false;
				miEventRemoveBObj.Enabled = false;
				dgvEvents.ClearSelection();
			}
		}
		private void contextVariables_Opening(object sender, CancelEventArgs e)
		{
			Point ptClient = dgvVariables.PointToClient(Cursor.Position);
			DataGridView.HitTestInfo hti = dgvVariables.HitTest(ptClient.X, ptClient.Y);
			if ( hti.Type == DataGridViewHitTestType.ColumnHeader ) {
				e.Cancel = true;
			} else if ( hti.Type == DataGridViewHitTestType.Cell ) {
				miVariableRemove.Enabled = true;
				miVariableRemoveBObj.Enabled = true;
				dgvVariables.Rows[hti.RowIndex].Selected = true;
			} else {
				miVariableRemove.Enabled = false;
				miVariableRemoveBObj.Enabled = false;
				dgvVariables.ClearSelection();
			}
		}

		private void miNewMethod_Click(object sender, EventArgs e)
		{
			addMethod();
		}
		private void miNewEvent_Click(object sender, EventArgs e)
		{
			addEvent();
		}
		private void miNewVariable_Click(object sender, EventArgs e)
		{
			addVariable();
		}
		
		private void miMethodRemoveInput_Click(object sender, EventArgs e)
		{
			if ( dgvMethods.SelectedRows.Count == 0 )
				return;

			( (Repository.WorkflowMethod)dgvMethods.SelectedRows[0].DataBoundItem )
				.InputBusinessObject = null;
			dgvMethods.UpdateCellValue(colMethodInputBO.Index, dgvMethods.SelectedRows[0].Index);
		}
		private void miMethodRemoveOutput_Click(object sender, EventArgs e)
		{
			if ( dgvMethods.SelectedRows.Count == 0 )
				return;

			( (Repository.WorkflowMethod)dgvMethods.SelectedRows[0].DataBoundItem )
				.OutputBusinessObject = null;
			dgvMethods.UpdateCellValue(colMethodOutputBO.Index, dgvMethods.SelectedRows[0].Index);
		}
		private void miMethodRemove_Click(object sender, EventArgs e)
		{
			removeMethod();
		}

		private void miEventRemoveBObj_Click(object sender, EventArgs e)
		{
			if ( dgvEvents.SelectedRows.Count == 0 )
				return;

			( (Repository.WorkflowEvent)dgvEvents.SelectedRows[0].DataBoundItem )
				.BusinessObject = null;
			dgvEvents.UpdateCellValue(colEventBO.Index, dgvEvents.SelectedRows[0].Index);
		}
		private void miEventRemove_Click(object sender, EventArgs e)
		{
			removeEvent();
		}

		private void miVariableRemoveBObj_Click(object sender, EventArgs e)
		{
			if ( dgvVariables.SelectedRows.Count == 0 )
				return;

			( (Repository.WorkflowField)dgvVariables.SelectedRows[0].DataBoundItem )
				.BusinessObject = null;
			dgvVariables.UpdateCellValue(colVariableDataType.Index, dgvVariables.SelectedRows[0].Index);
		}
		private void miVariableRemove_Click(object sender, EventArgs e)
		{
			dgvVariables.Rows.RemoveAt(dgvVariables.SelectedRows[0].Index);
		}
		#endregion

		private void dgvVariables_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colVariableDataType.Index ) {
				if ( dgvVariables[e.ColumnIndex, e.RowIndex].Value == null ) {
					Repository.WorkflowField wf = dgvVariables.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowField;
					if ( wf != null && string.IsNullOrEmpty(wf.Name) ) {
						_bsVariables.Remove(wf);
						wf.Delete(false);
					}
				}
			}
		}
		private void dgvMethods_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colMethodName.Index ) {
				if ( dgvMethods[e.ColumnIndex, e.RowIndex].Value == null ) {
					Repository.WorkflowMethod wm = dgvMethods.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowMethod;
					if ( wm != null && string.IsNullOrEmpty(wm.Name) ) {
						_bsMethods.Remove(wm);
						wm.Delete(false);
					}
				}
			}
		}
		private void dgvEvents_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colEventName.Index ) {
				if ( dgvEvents[e.ColumnIndex, e.RowIndex].Value == null ) {
					Repository.WorkflowEvent we = dgvEvents.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowEvent;
					if ( we != null && string.IsNullOrEmpty(we.Name) ) {
						_bsEvents.Remove(we);
						we.Delete(false);
					}
				}
			}
		}

		private void dgvVariables_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colVariableDataType.Index ) {
				colVariableDataType.Items.Add(
					( (Repository.WorkflowField)dgvVariables.Rows[e.RowIndex].DataBoundItem ).DataType);
			}
		}

		private void _bsVariables_ListChanged(object sender, ListChangedEventArgs e)
		{
		}
		private void _bsVariables_CurrentChanged(object sender, EventArgs e)
		{
			if ( _currentField != null && _currentField != (Repository.WorkflowField)_bsVariables.Current ) {
				if ( !_bsVariables.Contains(_currentField) ) {
					// item deleted
					MemberCreationService memberCreate = (MemberCreationService)_serviceProvider.GetService(typeof(IMemberCreationService));
					Debug.Assert(memberCreate != null);
					memberCreate.RemoveProperty(_workflow.ExtendedProperties.FullName,
												_currentOldName, null);
					memberCreate.RemoveField(_workflow.ExtendedProperties.FullName,
											 _currentOldName + "Property");
				}
			}
			_currentField = _bsVariables.Current as Repository.WorkflowField;
			if ( _currentField == null ) {
				_currentOldName = "";
				_currentOldType = "";
			} else {
				_currentOldName = _currentField.Name;
				_currentOldType = _currentField.DataType;
			}
		}
		private void _bsVariables_CurrentItemChanged(object sender, EventArgs e)
		{
			Repository.WorkflowField field = _bsVariables.Current as Repository.WorkflowField;
			if ( _currentField == null || field == null ) return;

			bool isnewname = false, isnewtype = false;
			if ( field.Name != _currentOldName ) isnewname = true;
			if ( field.DataType != _currentOldType ) isnewtype = true;
			if ( isnewname || isnewtype ) {
				TypeProvider typeProvider = (TypeProvider)_serviceProvider.GetService(typeof(ITypeProvider));
				MemberCreationService memberCreate = (MemberCreationService)_serviceProvider.GetService(typeof(IMemberCreationService));
				Debug.Assert(typeProvider != null);
				Debug.Assert(memberCreate != null);
				Type oldType = Global.Data.GetDOTNETTypeofXSDDataType(_currentOldType);
				if ( oldType == null ) {
					oldType = typeProvider.GetType(_currentOldType);
				}
				Type newType = Global.Data.GetDOTNETTypeofXSDDataType(field.DataType);
				if ( newType == null ) {
					newType = typeProvider.GetType(field.DataType);
				}
				try {
					memberCreate.UpdateProperty(_workflow.ExtendedProperties.FullName,
						_currentOldName, oldType, field.Name, newType, null, true, false);

					_currentOldName = field.Name;
					_currentOldType = field.DataType;
				} catch ( Exception ex ) {
					MessageBox.Show(ex.Message, "Change Process Variable Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
					field.Name = _currentOldName;
					field.DataType = _currentOldType;
					if ( isnewname ) {
						dgvVariables.CurrentCell = dgvVariables.CurrentRow.Cells[colVariableName.Index];
						dgvVariables.BeginEdit(true);
					} else if ( isnewtype ) {
						dgvVariables.CurrentCell = dgvVariables.CurrentRow.Cells[colVariableDataType.Index];
						dgvVariables.BeginEdit(true);
					}
				}
			}
		}

		private void dgvMethods_CellContentClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colMethodUIConfig.Index ) {
				Repository.WorkflowMethod wm = dgvMethods.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowMethod;
				FormUIConfigMethod frm = new FormUIConfigMethod(wm);
				frm.ShowDialog();
			}
		}
		private void dgvMethods_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colMethodUIConfig.Index ) {
				e.ToolTipText = "Open UI Configuration Dialog...";
			}
		}
		private void dgvMethods_CurrentCellDirtyStateChanged(object sender, EventArgs e)
		{

		}


		private void dgvEvents_CellContentClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colEventUIConfig.Index ) {
				Repository.WorkflowEvent we = dgvEvents.Rows[e.RowIndex].DataBoundItem as Repository.WorkflowEvent;
				FormUIConfigEvent frm = new FormUIConfigEvent(we);
				frm.ShowDialog();
			}
		}
		private void dgvEvents_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.ColumnIndex == colEventUIConfig.Index ) {
				e.ToolTipText = "Open UI Configuration Dialog...";
			}
		}

		private void tsmiEditGroups_Click(object sender, EventArgs e)
		{
			Forms.FormMashupControlGroups frm = new FormMashupControlGroups(_workflow);
			frm.ShowDialog();
		}

		private void dgvEvents_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{

		}

		private void FormWFInterface_Load(object sender, EventArgs e)
		{
			dgvVariables.ClearSelection();
			dgvMethods.ClearSelection();
			dgvEvents.ClearSelection();
		}

		private void tabCtrlWFInterface_Selected(object sender, TabControlEventArgs e)
		{
			if ( e.TabPage == tabEvents ) {
				dgvEvents.ClearSelection();
			} else if ( e.TabPage == tabMethods ) {
				dgvMethods.ClearSelection();
			} else if ( e.TabPage == tabVariables ) {
				dgvVariables.ClearSelection();
			}
		}

		#endregion

		private void dataGrid_KeyPressed(object sender, KeyPressEventArgs e)
		{
			e.Handled = !Helpers.IsValidCharForName(e.KeyChar);
		}

		#endregion

		private void dgvMethods_CellValueChanged(object sender, DataGridViewCellEventArgs e)
		{

		}

		private void dataGrid_KeyUp(object sender, KeyEventArgs e)
		{
			if(dgvMethods.IsCurrentCellInEditMode)return;
			if ( e.KeyCode == Keys.Delete ) {
				removeMethod();
				e.Handled = true;
			}
		}

		private void dgvEvents_KeyUp(object sender, KeyEventArgs e)
		{
			if ( dgvEvents.IsCurrentCellInEditMode ) return;
			if ( e.KeyCode == Keys.Delete ) {
				removeEvent();
				e.Handled = true;
			}
		}

		private void dgvVariables_KeyUp(object sender, KeyEventArgs e)
		{
		}

		private void dgvMethods_KeyDown(object sender, KeyEventArgs e)
		{
			if ( dgvMethods.IsCurrentCellInEditMode ) return;
			if ( e.KeyCode == Keys.Delete ) {
				removeMethod();
				e.Handled = true;
			}
		}

		private void dgvEvents_KeyDown(object sender, KeyEventArgs e)
		{
			if ( dgvEvents.IsCurrentCellInEditMode ) return;
			if ( e.KeyCode == Keys.Delete ) {
				removeEvent();
				e.Handled = true;
			}
		}

		private void dgvVariables_KeyDown(object sender, KeyEventArgs e)
		{

		}
	}
}